using System.Collections.Generic;
using System.Threading;

namespace System.Linq.Reactive
{
    public class TimeIntervalObservable : IObservableEx<TimeSpan>
    {
        private readonly TimeSpan f_Interval;
        private bool f_Work = false;
        private object f_SyncObject = new object();
        private Thread f_Thread;
        private readonly List<SimpleObserverEx<TimeSpan>> f_Observers = new List<SimpleObserverEx<TimeSpan>>();

        public TimeIntervalObservable(TimeSpan interval, bool Start = false)
        {
            f_Interval = interval;
            if(Start) this.Start();
        }

        public void Start()
        {
            lock(f_SyncObject)
            {
                if(f_Work) return;
                f_Work = true;
                var NeedReset = f_Thread != null;
                f_Thread = new Thread(ThreadMethod) { IsBackground = true };
                if(NeedReset) f_Observers.ForEach(o => o.OnReset());
                f_Thread.Start();
            }
        }

        public void Stop()
        {
            lock(f_SyncObject)
            {
                if(!f_Work) return;
                f_Work = false;
                if(!f_Thread.Join(f_Interval.Milliseconds * 2))
                    f_Thread.Abort();
            }
            foreach(var observer in f_Observers.ToArray())
                observer.OnComplited();
        }

        private void ThreadMethod()
        {
            while(f_Work)
            {
                var time = DateTime.Now.TimeOfDay;
                foreach(var observer in f_Observers.ToArray())
                    observer.OnNext(time);
                Thread.Sleep(f_Interval);
            }
        }

        public IObserverEx<TimeSpan> GetObserver()
        {
            var o = new SimpleObserverEx<TimeSpan>();
            f_Observers.Add(o);
            return o;
        }
    }
}